import time
import logging
import numpy as np
import pandas as pd
from typing import Dict, Any, List, Optional
from datetime import datetime, timedelta

# 配置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger('CloudSimulator')

class SimulationResult:
    """仿真结果类，存储仿真验证的结果和风险评估"""
    def __init__(self):
        self.success = False
        self.risk_score = 0.0
        self.max_drawdown = 0.0
        self.estimated_profit = 0.0
        self.probability_of_success = 0.0
        self.slippage_estimate = 0.0
        self.market_impact_estimate = 0.0
        self.execution_time_ms = 0
        self.simulation_duration_ms = 0
        self.messages = []
        self.metrics = {}
        self.timestamp = time.time()
    
    def add_message(self, message: str):
        """添加消息到结果"""
        self.messages.append(message)
        
    def update_metrics(self, metrics: Dict[str, Any]):
        """更新指标"""
        self.metrics.update(metrics)
        
    def pass_risk_check(self, risk_threshold: float = 0.7) -> bool:
        """检查是否通过风险评估
        risk_threshold: 风险阈值，得分低于该值通过检查
        """
        # 风险评分越低，风险越小，越容易通过检查
        return self.risk_score < risk_threshold and self.success
        
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典格式"""
        return {
            'success': self.success,
            'risk_score': self.risk_score,
            'max_drawdown': self.max_drawdown,
            'estimated_profit': self.estimated_profit,
            'probability_of_success': self.probability_of_success,
            'slippage_estimate': self.slippage_estimate,
            'market_impact_estimate': self.market_impact_estimate,
            'execution_time_ms': self.execution_time_ms,
            'simulation_duration_ms': self.simulation_duration_ms,
            'messages': self.messages,
            'metrics': self.metrics,
            'timestamp': self.timestamp
        }

class CloudSimulator:
    """云端仿真模块，负责在触发前进行微型回测验证"""
    def __init__(self, config=None):
        self.config = config or {
            'simulation_window_seconds': 500,  # 0.5秒仿真窗口
            'risk_check_enabled': True,
            'historical_data_points': 100,  # 用于仿真的历史数据点数量
            'max_execution_time_ms': 50,  # 最大执行时间（毫秒）
            'debug_mode': False
        }
        
        # 仿真历史记录
        self.simulation_history = []
        
        # 性能统计
        self.performance_stats = {
            'total_simulations': 0,
            'successful_simulations': 0,
            'failed_simulations': 0,
            'avg_execution_time_ms': 0,
            'avg_simulation_duration_ms': 0,
            'avg_risk_score': 0
        }
        
        # 市场状态模拟器
        self.market_simulator = MarketDataSimulator()
        
        # 风险评估器
        self.risk_evaluator = RiskEvaluator()
        
        logger.info("CloudSimulator initialized")
    
    def run(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> SimulationResult:
        """运行仿真验证
        rule: 触发的规则
        market_data: 当前市场数据
        """
        # 创建仿真结果对象
        result = SimulationResult()
        
        # 记录开始时间
        start_time = time.time()
        
        try:
            # 更新性能统计
            self.performance_stats['total_simulations'] += 1
            
            # 验证规则和市场数据
            if not self._validate_inputs(rule, market_data, result):
                # 输入验证失败
                result.success = False
                self.performance_stats['failed_simulations'] += 1
                return result
            
            # 生成历史数据（实际应用中应从数据源获取）
            historical_data = self._generate_historical_data(rule, market_data)
            
            # 运行微型回测
            self._run_micro_backtest(rule, market_data, historical_data, result)
            
            # 执行风险检查
            if self.config['risk_check_enabled']:
                self.risk_evaluator.evaluate_risk(rule, market_data, result)
            
            # 计算执行时间
            result.execution_time_ms = (time.time() - start_time) * 1000
            
            # 更新性能统计
            if result.success:
                self.performance_stats['successful_simulations'] += 1
            else:
                self.performance_stats['failed_simulations'] += 1
            
            # 更新平均执行时间（使用指数加权移动平均）
            self.performance_stats['avg_execution_time_ms'] = (
                self.performance_stats['avg_execution_time_ms'] * 0.9 +
                result.execution_time_ms * 0.1
            )
            
            # 更新平均仿真持续时间
            self.performance_stats['avg_simulation_duration_ms'] = (
                self.performance_stats['avg_simulation_duration_ms'] * 0.9 +
                result.simulation_duration_ms * 0.1
            )
            
            # 更新平均风险评分
            self.performance_stats['avg_risk_score'] = (
                self.performance_stats['avg_risk_score'] * 0.9 +
                result.risk_score * 0.1
            )
            
            # 记录到历史
            self._record_history(rule, market_data, result)
            
            # 检查执行时间是否超过限制
            if result.execution_time_ms > self.config['max_execution_time_ms']:
                logger.warning(f"Simulation execution time exceeded limit: {result.execution_time_ms}ms > {self.config['max_execution_time_ms']}ms")
                
        except Exception as e:
            result.success = False
            result.add_message(f"Simulation failed with error: {str(e)}")
            logger.error(f"Simulation error: {str(e)}")
            self.performance_stats['failed_simulations'] += 1
        
        return result
    
    def _validate_inputs(self, rule: Dict[str, Any], market_data: Dict[str, Any], result: SimulationResult) -> bool:
        """验证输入参数"""
        # 检查规则是否有效
        if not rule or not isinstance(rule, dict):
            result.add_message("Invalid rule format")
            logger.error("Invalid rule format")
            return False
        
        # 检查是否包含必要的规则字段
        required_rule_fields = ['symbol', 'action', 'conditions']
        for field in required_rule_fields:
            if field not in rule:
                result.add_message(f"Missing required rule field: {field}")
                logger.error(f"Missing required rule field: {field}")
                return False
        
        # 检查市场数据是否有效
        if not market_data or not isinstance(market_data, dict):
            result.add_message("Invalid market data format")
            logger.error("Invalid market data format")
            return False
        
        # 检查股票代码是否在市场数据中
        symbol = rule['symbol'].lower()
        if f'{symbol}_price' not in market_data:
            result.add_message(f"No market data for symbol: {rule['symbol']}")
            logger.error(f"No market data for symbol: {rule['symbol']}")
            return False
        
        return True
    
    def _generate_historical_data(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> pd.DataFrame:
        """生成历史数据（实际应用中应从数据源获取）"""
        # 实际应用中，这里应该从历史数据库获取数据
        # 这里提供一个模拟实现
        symbol = rule['symbol'].lower()
        current_price = market_data.get(f'{symbol}_price', 100.0)
        volatility = market_data.get(f'{symbol}_volatility', 0.2)
        
        # 创建时间索引
        now = datetime.now()
        timestamps = [now - timedelta(seconds=i) for i in range(self.config['historical_data_points'] - 1, -1, -1)]
        
        # 模拟价格序列（使用几何布朗运动模型）
        returns = np.random.normal(0, volatility / np.sqrt(252 * 86400), self.config['historical_data_points'])
        prices = current_price * np.exp(np.cumsum(returns))
        
        # 模拟成交量
        avg_volume = market_data.get(f'{symbol}_volume', 1000000) / 86400  # 假设日均成交量，转换为每秒
        volumes = np.random.poisson(avg_volume, self.config['historical_data_points'])
        
        # 创建DataFrame
        historical_data = pd.DataFrame({
            'timestamp': timestamps,
            'price': prices,
            'volume': volumes
        })
        
        # 添加一些技术指标
        historical_data['ma5'] = historical_data['price'].rolling(window=5).mean()
        historical_data['ma10'] = historical_data['price'].rolling(window=10).mean()
        historical_data['ma20'] = historical_data['price'].rolling(window=20).mean()
        historical_data['returns'] = historical_data['price'].pct_change()
        
        # 填充缺失值
        historical_data.fillna(method='bfill', inplace=True)
        
        return historical_data
    
    def _run_micro_backtest(self, rule: Dict[str, Any], market_data: Dict[str, Any], historical_data: pd.DataFrame, result: SimulationResult):
        """运行微型回测"""
        # 记录回测开始时间
        backtest_start_time = time.time()
        
        try:
            symbol = rule['symbol']
            action = rule['action']
            current_price = market_data.get(f'{symbol.lower()}_price', 100.0)
            
            # 模拟执行策略
            simulated_trades = self._simulate_trades(rule, historical_data)
            
            if not simulated_trades:
                result.success = False
                result.add_message("No simulated trades generated")
                return
            
            # 计算回测指标
            self._calculate_backtest_metrics(rule, historical_data, simulated_trades, current_price, result)
            
            # 模拟市场影响和滑点
            self._simulate_market_impact_and_slippage(rule, market_data, result)
            
            # 计算仿真持续时间
            result.simulation_duration_ms = (time.time() - backtest_start_time) * 1000
            
            # 设置回测成功标志
            result.success = True
            
        except Exception as e:
            result.success = False
            result.add_message(f"Micro backtest failed: {str(e)}")
            logger.error(f"Micro backtest error: {str(e)}")
    
    def _simulate_trades(self, rule: Dict[str, Any], historical_data: pd.DataFrame) -> List[Dict[str, Any]]:
        """模拟交易"""
        trades = []
        
        try:
            # 简单模拟，根据历史数据中的规则条件触发交易
            # 实际应用中应该更复杂，考虑更多因素
            symbol = rule['symbol']
            action = rule['action']
            
            # 遍历历史数据，模拟交易
            for i in range(1, len(historical_data)):
                # 简单模拟：如果价格上涨超过0.5%，模拟买入
                if action == 'BUY' and historical_data['returns'].iloc[i] > 0.005:
                    trade = {
                        'timestamp': historical_data['timestamp'].iloc[i],
                        'price': historical_data['price'].iloc[i],
                        'quantity': 100,  # 模拟买入100股
                        'side': 'BUY',
                        'symbol': symbol
                    }
                    trades.append(trade)
                
                # 简单模拟：如果价格下跌超过0.5%，模拟卖出
                elif action == 'SELL' and historical_data['returns'].iloc[i] < -0.005:
                    trade = {
                        'timestamp': historical_data['timestamp'].iloc[i],
                        'price': historical_data['price'].iloc[i],
                        'quantity': 100,  # 模拟卖出100股
                        'side': 'SELL',
                        'symbol': symbol
                    }
                    trades.append(trade)
                    
        except Exception as e:
            logger.error(f"Trade simulation error: {str(e)}")
        
        return trades
    
    def _calculate_backtest_metrics(self, rule: Dict[str, Any], historical_data: pd.DataFrame, trades: List[Dict[str, Any]], current_price: float, result: SimulationResult):
        """计算回测指标"""
        if not trades:
            return
        
        try:
            # 计算总收益
            total_profit = 0
            position = 0
            entry_price = 0
            
            for trade in trades:
                if trade['side'] == 'BUY':
                    position += trade['quantity']
                    entry_price = trade['price']
                elif trade['side'] == 'SELL' and position > 0:
                    # 计算每股利润
                    profit_per_share = trade['price'] - entry_price
                    # 计算总利润
                    total_profit += profit_per_share * min(trade['quantity'], position)
                    # 减少仓位
                    position -= min(trade['quantity'], position)
            
            # 如果仍有未平仓位，使用当前价格计算未实现利润
            if position > 0:
                profit_per_share = current_price - entry_price
                total_profit += profit_per_share * position
            
            # 计算成功率概率（基于历史表现）
            # 简单模拟：假设最近n次相同条件下的成功率
            success_rate = min(1.0, max(0.0, 0.5 + np.random.normal(0, 0.1)))  # 随机在0.4-0.6之间
            
            # 更新结果
            result.estimated_profit = total_profit
            result.probability_of_success = success_rate
            
            # 计算最大回撤（简化版）
            prices = historical_data['price'].values
            running_max = np.maximum.accumulate(prices)
            drawdown = (prices - running_max) / running_max
            max_drawdown = np.min(drawdown) if len(drawdown) > 0 else 0
            
            result.max_drawdown = max_drawdown
            
            # 更新其他指标
            result.update_metrics({
                'total_trades': len(trades),
                'win_rate': success_rate,
                'profit_factor': 1.5 + np.random.normal(0, 0.2)  # 随机在1.3-1.7之间
            })
            
        except Exception as e:
            logger.error(f"Backtest metrics calculation error: {str(e)}")
    
    def _simulate_market_impact_and_slippage(self, rule: Dict[str, Any], market_data: Dict[str, Any], result: SimulationResult):
        """模拟市场影响和滑点"""
        try:
            # 获取股票代码和当前流动性
            symbol = rule['symbol'].lower()
            liquidity_score = market_data.get('liquidity_score', 0.5)
            
            # 计算估计的订单大小（简化版）
            equity = 100000  # 假设账户资产为10万
            risk_per_trade = 0.02  # 假设每笔交易风险2%
            
            # 估计订单大小
            estimated_order_size = equity * risk_per_trade
            
            # 计算市场影响（基于流动性和订单大小）
            # 流动性越低，市场影响越大
            # 订单相对于市场容量越大，市场影响越大
            market_impact = 0.01 * (1 - liquidity_score) * (estimated_order_size / 10000)  # 简化公式
            
            # 计算滑点估计（基于市场波动和执行策略）
            volatility = market_data.get(f'{symbol}_volatility', 0.2)
            execution_strategy = rule.get('execution_strategy', 'MARKET')
            
            # 根据执行策略调整滑点估计
            strategy_slippage_factors = {
                'MARKET': 1.0,
                'LIMIT': 0.3,
                'VWAP': 0.5,
                'TWAP': 0.6,
                'ICEBERG': 0.4,
                'POV': 0.5
            }
            
            slippage_factor = strategy_slippage_factors.get(execution_strategy, 1.0)
            slippage = volatility * 0.01 * slippage_factor  # 简化公式
            
            # 更新结果
            result.market_impact_estimate = market_impact
            result.slippage_estimate = slippage
            
            # 更新指标
            result.update_metrics({
                'estimated_order_size': estimated_order_size,
                'liquidity_score': liquidity_score,
                'volatility': volatility
            })
            
        except Exception as e:
            logger.error(f"Market impact and slippage simulation error: {str(e)}")
    
    def _record_history(self, rule: Dict[str, Any], market_data: Dict[str, Any], result: SimulationResult):
        """记录仿真历史"""
        # 创建历史记录
        history_record = {
            'timestamp': time.time(),
            'rule_id': rule.get('rule_id', 'unknown'),
            'symbol': rule.get('symbol', 'unknown'),
            'result': result.to_dict(),
            'market_data_snapshot': {
                'price': market_data.get(f"{rule.get('symbol', '').lower()}_price", 0),
                'volume': market_data.get(f"{rule.get('symbol', '').lower()}_volume", 0),
                'volatility': market_data.get(f"{rule.get('symbol', '').lower()}_volatility", 0),
                'liquidity_score': market_data.get('liquidity_score', 0)
            }
        }
        
        # 添加到历史记录
        self.simulation_history.append(history_record)
        
        # 限制历史记录长度，避免内存溢出
        max_history_length = 10000
        if len(self.simulation_history) > max_history_length:
            self.simulation_history = self.simulation_history[-max_history_length:]
    
    def get_simulation_history(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
        """获取仿真历史记录
        limit: 返回的最大记录数
        """
        if limit is not None:
            return self.simulation_history[-limit:]
        return self.simulation_history
    
    def get_performance_stats(self) -> Dict[str, Any]:
        """获取性能统计信息"""
        return self.performance_stats.copy()
    
    def reset_history(self):
        """重置历史记录"""
        self.simulation_history = []
        logger.info("Simulation history reset")
    
    def reset_performance_stats(self):
        """重置性能统计"""
        self.performance_stats = {
            'total_simulations': 0,
            'successful_simulations': 0,
            'failed_simulations': 0,
            'avg_execution_time_ms': 0,
            'avg_simulation_duration_ms': 0,
            'avg_risk_score': 0
        }
        logger.info("Performance statistics reset")
    
    def set_config(self, **kwargs):
        """设置模拟器配置"""
        for key, value in kwargs.items():
            if key in self.config:
                self.config[key] = value
        logger.info(f"CloudSimulator configuration updated: {kwargs}")
        return self.config

class MarketDataSimulator:
    """市场数据模拟器"""
    def __init__(self):
        self.symbol_data = {}
        logger.info("MarketDataSimulator initialized")
    
    def generate_market_data(self, symbol: str, current_price: float, volatility: float) -> Dict[str, Any]:
        """生成模拟市场数据"""
        # 模拟买卖盘数据
        bid_price = current_price * (1 - np.random.uniform(0.0001, 0.001))
        ask_price = current_price * (1 + np.random.uniform(0.0001, 0.001))
        
        # 模拟成交量
        base_volume = 1000000
        volume = base_volume * (1 + np.random.normal(0, 0.1))
        
        # 模拟买卖深度
        bid_depth = np.random.randint(1000, 10000)
        ask_depth = np.random.randint(1000, 10000)
        
        # 创建市场数据
        market_data = {
            'price': current_price,
            'bid': bid_price,
            'ask': ask_price,
            'volume': volume,
            'bid_depth': bid_depth,
            'ask_depth': ask_depth,
            'volatility': volatility,
            'spread': ask_price - bid_price,
            'mid_price': (bid_price + ask_price) / 2,
            'timestamp': time.time()
        }
        
        # 存储符号数据
        self.symbol_data[symbol] = market_data
        
        return market_data

class RiskEvaluator:
    """风险评估器"""
    def __init__(self):
        logger.info("RiskEvaluator initialized")
    
    def evaluate_risk(self, rule: Dict[str, Any], market_data: Dict[str, Any], result: SimulationResult):
        """评估交易风险"""
        # 计算各项风险指标
        market_risk = self._evaluate_market_risk(rule, market_data)
        liquidity_risk = self._evaluate_liquidity_risk(rule, market_data)
        execution_risk = self._evaluate_execution_risk(rule, market_data, result)
        strategy_risk = self._evaluate_strategy_risk(rule, market_data)
        
        # 综合风险评分（加权平均）
        # 权重可以根据实际需求调整
        risk_score = (
            0.3 * market_risk +
            0.25 * liquidity_risk +
            0.25 * execution_risk +
            0.2 * strategy_risk
        )
        
        # 确保风险评分在0-1之间
        risk_score = min(1.0, max(0.0, risk_score))
        
        # 更新结果
        result.risk_score = risk_score
        
        # 添加风险评估消息
        result.add_message(f"Risk evaluation completed: market_risk={market_risk:.3f}, liquidity_risk={liquidity_risk:.3f}, execution_risk={execution_risk:.3f}, strategy_risk={strategy_risk:.3f}, total_risk={risk_score:.3f}")
    
    def _evaluate_market_risk(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> float:
        """评估市场风险"""
        # 获取市场波动和VIX
        symbol = rule['symbol'].lower()
        volatility = market_data.get(f'{symbol}_volatility', 0.2)
        vix = market_data.get('vix', 15.0)
        
        # 计算市场风险评分
        # 波动越大，风险越高
        market_risk = min(1.0, (volatility + (vix / 100)) / 2)
        
        return market_risk
    
    def _evaluate_liquidity_risk(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> float:
        """评估流动性风险"""
        # 获取流动性评分
        liquidity_score = market_data.get('liquidity_score', 0.5)
        
        # 计算流动性风险评分
        # 流动性越低，风险越高
        liquidity_risk = 1 - liquidity_score
        
        return liquidity_risk
    
    def _evaluate_execution_risk(self, rule: Dict[str, Any], market_data: Dict[str, Any], result: SimulationResult) -> float:
        """评估执行风险"""
        # 获取市场影响和滑点估计
        market_impact = result.market_impact_estimate
        slippage = result.slippage_estimate
        
        # 计算执行风险评分
        # 市场影响和滑点越大，风险越高
        execution_risk = min(1.0, (market_impact + slippage) * 50)  # 放大倍数，使结果在0-1之间
        
        return execution_risk
    
    def _evaluate_strategy_risk(self, rule: Dict[str, Any], market_data: Dict[str, Any]) -> float:
        """评估策略风险"""
        # 获取策略相关参数
        risk_per_trade = rule.get('risk_per_trade', 0.02)  # 默认每笔交易风险2%
        leverage = rule.get('leverage', 1.0)  # 默认杠杆1倍
        
        # 计算策略风险评分
        # 风险比例和杠杆越高，风险越高
        strategy_risk = min(1.0, risk_per_trade * leverage * 50)  # 放大倍数，使结果在0-1之间
        
        return strategy_risk

# 示例使用
if __name__ == "__main__":
    # 创建CloudSimulator实例
    simulator = CloudSimulator()
    
    # 创建一个简单的规则
    rule = {
        'rule_id': 1,
        'symbol': 'AAPL',
        'action': 'BUY',
        'conditions': [
            {
                'field': 'price_above_ma20',
                'comparator': '==',
                'value': True
            },
            {
                'field': 'volume_ratio',
                'comparator': '>',
                'value': 2.0
            }
        ],
        'execution_strategy': 'VWAP',
        'order_type': 'MARKET',
        'risk_per_trade': 0.02
    }
    
    # 创建模拟市场数据
    market_data = {
        'aapl_price': 150.0,
        'aapl_volume': 1000000,
        'aapl_volatility': 0.2,
        'aapl_ma20': 148.8,
        'price_above_ma20': True,
        'volume_ratio': 2.5,
        'vix': 18.0,
        'liquidity_score': 0.85
    }
    
    print("Running simulation...")
    
    # 运行仿真
    result = simulator.run(rule, market_data)
    
    # 输出结果
    print(f"Simulation success: {result.success}")
    print(f"Risk score: {result.risk_score}")
    print(f"Estimated profit: {result.estimated_profit}")
    print(f"Probability of success: {result.probability_of_success}")
    print(f"Execution time: {result.execution_time_ms}ms")
    print(f"Messages: {result.messages}")
    
    # 检查是否通过风险检查
    if result.pass_risk_check():
        print("Simulation passed risk check")
    else:
        print("Simulation failed risk check")
    
    # 获取性能统计
    stats = simulator.get_performance_stats()
    print(f"Performance stats: {stats}")
    
    # 获取仿真历史
    history = simulator.get_simulation_history()
    print(f"Simulation history count: {len(history)}")